/**
 *  Copyright 2011 Pavlov Dm.
 *  Licensed under the MIT License
 */


package org.motiv.config;

import org.motiv.core.CacheException;

import java.io.InputStream;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import org.apache.log4j.Logger;
/**
 * A utility class which create configure from XML.
  * @author Pavlov Dm
 */
public final class ConfigurationFactory {
	/** Logger instance */
	public static final Logger LOG=Logger.getLogger(ConfigurationFactory.class);
	
    private static final String DEFAULT_CONFIG_FILE = "cache.xml";
	
	private static final String XML_CONFIG_ROOT_TAG = "l2cache";
	
	private static final String XML_CONFIG_CACHE_TAG = "cache";
    /**
     * Constructor.
     */
    private ConfigurationFactory() { }

    /**
     * Configures from an XML file.
     */
    public static Configuration parseConfiguration() throws CacheException {
		Configuration configuration = new Configuration();
        InputStream is = ConfigurationFactory.class.getResourceAsStream("/"+DEFAULT_CONFIG_FILE);
		if(is != null){
			Document configXml = streamToDocument(is);
			parseConfig(configXml,configuration);
		} else {
			LOG.warn("Cache configuration file not found!");
			return new DefaultConfiguration();
		}
        return configuration;
    }
	/**
    * Read XML types configuration file as DOM.
	* @param is XML input stream
	* @return XML document object
	*/
	private static Document streamToDocument(InputStream is){
		Document xmlDoc = null;
		try{
			DocumentBuilder docBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
			xmlDoc = docBuilder.parse(is);
			xmlDoc.getDocumentElement().normalize();
		} catch(SAXException ex){
			LOG.error("Parse configuration file error! Detail: "+ex.getMessage());
		} catch (Exception ex){
			LOG.error("Parse configuration file error! Detail: "+ex.getMessage());
		} finally{
			return xmlDoc;
		}
	}
	/**
	* Parse configuration method
	*/
	public static void parseConfig(Document xmlConfig,Configuration configuration){
		//Start parse XML
		if(xmlConfig!=null){
		
			String sRootTagName = xmlConfig.getDocumentElement().getNodeName();
			
			if(sRootTagName!=null && sRootTagName.equalsIgnoreCase(XML_CONFIG_ROOT_TAG)){
				
				NodeList cachesList = xmlConfig.getElementsByTagName(XML_CONFIG_CACHE_TAG);
				
				if(cachesList!=null){
				
					for (int iCacheIndex = 0; iCacheIndex < cachesList.getLength(); iCacheIndex++) {
					
						Node cacheNode = cachesList.item(iCacheIndex);
						
						if (cacheNode.getNodeType() == Node.ELEMENT_NODE) {
						
							CacheConfiguration cacheConfiguration = new CacheConfigurationParser(cacheNode).parseCache();
							
							if(cacheConfiguration!=null){
								configuration.addCacheConfiguration(cacheConfiguration);
							}
							
						}
					}
				} 
			} 
		} 
	}
}
